package com.hmall.user.service.impl;

import com.hmall.pojo.ItemFreeze;
import com.hmall.pojo.UserFreeze;
import com.hmall.user.mapper.UserMapper;
import com.hmall.pojo.User;
import com.hmall.user.service.IUserFreezeService;
import com.hmall.user.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.seata.core.context.RootContext;
import io.seata.rm.tcc.api.BusinessActionContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class UserService extends ServiceImpl<UserMapper, User> implements IUserService {
    @Autowired
    private IUserFreezeService iUserFreezeService;
    @Autowired
    private UserMapper userMapper;

    /**
     * 下单扣款 TCC -- try
     *
     * @param userId
     * @param money
     */
    @Override
    public void deductMoney(Long userId, Long money) {
        //获得全局事务
        String xid = RootContext.getXID();

        //解决业务悬挂问题
        UserFreeze userFreeze = iUserFreezeService.getById(userId);
        if (userFreeze != null) {
            log.info("处理业务悬挂问题。。。事务id：{},用户id：{},金额：{}", xid, userId, money);
            return;
        }

        //没有问题 做正常冻结
        log.info("账户扣款中。。。事务id：{},用户id：{},金额：{}", xid, userId, money);
        userMapper.deduct(userId, money);
        log.info("账户扣款成功！！！");

        log.info("新增冻结数据中。。。");
        userFreeze = new UserFreeze();
        userFreeze.setXid(xid);
        userFreeze.setFreezeMoney(Integer.parseInt(money.toString()));
        userFreeze.setState(UserFreeze.State.TRY);
        userFreeze.setUserId(userId.toString());
        iUserFreezeService.save(userFreeze);
        log.info("新增冻结数据成功！！！");
    }

    /**
     * TCC -- confirm
     *
     * @param context
     */
    @Override
    public void confirm(BusinessActionContext context) {
        //获取全局事务id
        String xid = context.getXid();

        //确认 删除冻结数据
        log.info("删除冻结数据中。。。事务id：{}", xid);
        boolean count = iUserFreezeService.removeById(xid);
        if (count) {
            log.info("删除冻结数据成功！！！");
        } else {
            log.error("删除冻结数据失败！！！");
        }
    }

    /**
     * TCC -- cancel
     *
     * @param context
     */
    @Override
    public void cancel(BusinessActionContext context) {
        //获取全局事务id、冻结数量、商品id等
        String xid = context.getXid();
        String userId = context.getActionContext("userId").toString();
        String money = context.getActionContext("money").toString();

        //解决空回滚问题
        UserFreeze userFreeze = iUserFreezeService.getById(xid);
        if (userFreeze == null) {//出现空回滚
            log.info("处理空回滚问题中。。。事务id：{},用户id：{},金额：{}",xid,userId,money);
            userFreeze = new UserFreeze();
            userFreeze.setUserId(userId);
            userFreeze.setState(UserFreeze.State.CANCEL);
            userFreeze.setFreezeMoney(Integer.parseInt(money));
            userFreeze.setXid(xid);
            iUserFreezeService.save(userFreeze);
            log.info("处理空回滚问题成功");

            return;
        }

        //解决幂等问题
        if (UserFreeze.State.CANCEL == userFreeze.getState()) {
            log.info("处理幂等问题中。。。事务id：{},用户id：{},金额：{}",xid,userId,money);
            return;
        }

        //正常取消 回滚商品数量
        log.info("回滚商品数量中。。。事务id：{},用户id：{},金额：{}",xid,userId,money);
        userMapper.refund(userId, money);
        log.info("回滚商品数量成功!!!");

        log.info("修改冻结数据中。。。事务id：{},用户id：{},金额：{}",xid,userId,money);
        userFreeze.setFreezeMoney(0);
        userFreeze.setState(UserFreeze.State.CANCEL);
        boolean count = iUserFreezeService.updateById(userFreeze);
        if (count) {
            log.info("修改冻结数据中成功!!!");
        } else {
            log.error("修改冻结数据中失败!!!");
        }
    }
}